package com.my.swas.common.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.my.swas.common.utils.CookieUtils;
import com.my.swas.common.utils.HttpContextUtils;
import com.my.swas.common.utils.SpringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * @Description:
 * @author: :MaYong
 * @Date: 2018/8/8 18:57
 */
@ConfigurationProperties(prefix = "jwt")
@Component
public class JWTUtils {
    //默认一天
    private static final int EXPIRE_TIME = 24*60*60*1000;

    /**
     * 校验token是否正确
     * @param jwtToken 密钥
     * @param userAccount 用户
     * @param secret 用户的密码
     * @return 是否正确
     */
    public static boolean verify(String jwtToken,String userAccount,String secret,Long userId) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("userAccount",userAccount)
                    .withClaim("userId",userId)
                    .build();
            verifier.verify(jwtToken);
            return true;
        } catch (Exception exception) {
            return false;
        }
    }



    /**
     * 获得token中的信息无需secret解密也能获得
     * @return token中包含的用户名
     */
    public static Long getUserId() {
        return getUserId(null);
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     * @return token中包含的用户名
     */
    public static String getUserAccount() {
        return getUserAccount(null);
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     * @return token中包含的用户名
     */
    public static Long getUserId(String jwtToken) {
        try {
            if(StringUtils.isEmpty(jwtToken)) {
                jwtToken = getJWTToken();
            }
            if(StringUtils.isEmpty(jwtToken)){
                return null;
            }
            DecodedJWT jwt = JWT.decode(jwtToken);
            return jwt.getClaim("userId").asLong();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     * @return token中包含的用户名
     */
    public static String getUserAccount(String jwtToken) {
        try {
            if(StringUtils.isEmpty(jwtToken)) {
                jwtToken = getJWTToken();
            }
            if(StringUtils.isEmpty(jwtToken)){
                return null;
            }
            DecodedJWT jwt = JWT.decode(jwtToken);
            return jwt.getClaim("userAccount").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }


    /**
     * 生成签名,5min后过期
     * @param secret 用户名
     * @return 加密的token
     */
    public static String sign(String userAccount,String secret,Long userId) {
        try {
            Date date = new Date(System.currentTimeMillis()+EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            // 附带username信息
            return JWT.create()
                    //这里保存的所有信息全部使用String类型，否者在获取的时候asString处理错误
                    .withClaim("userAccount",userAccount)
                    .withClaim("userId",userId)
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    public static String getJWTToken(){
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        return getJWTToken(request);
    }

    public static String getJWTToken(HttpServletRequest request){
        String token = request.getHeader(JWTToken.AUTH_TOKEN);
        if(StringUtils.isEmpty(token)){
            token = CookieUtils.getCookieValue(request, JWTToken.AUTH_TOKEN);
        }
        return token;
    }

}
